﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WorldOnFire
{
    public static class SEventSystem
    {
        // Lists of clients (one for each event)
        private static List<ABCClient>[] m_ClientLists;

        // Queue of events
        private static Queue<ABCEvent> m_EventList;

        /// <summary>
        /// Registers a client for an event.
        /// </summary>
        /// <param name="_Client">The client to register.</param>
        /// <param name="_eID">The event to register the client for.</param>
        public static void RegisterClient(ABCClient _Client, ABCEvent.eEventID _eID)
        {
            // Remove the client from the appropriate list
            m_ClientLists[(int)_eID].Add(_Client);
        }

        /// <summary>
        /// Unregisters a client for an event.
        /// </summary>
        /// <param name="_Client">The client to unregister.</param>
        /// <param name="_eID">The event to unregister the client for.</param>
        public static void UnRegisterClient(ABCClient _Client, ABCEvent.eEventID _eID)
        {
            // For each event
            for (int iEvent = 0; iEvent < (int)ABCEvent.eEventID.COUNT; ++iEvent)
            {
                // Remove the client to the appropriate list
                m_ClientLists[iEvent].Remove(_Client);
            }
        }

        /// <summary>
        /// Unregisters a client for an event.
        /// </summary>
        /// <param name="_Client">The client to unregister.</param>
        /// <param name="_eID">The event to unregister the client for.</param>
        public static void UnRegisterClientAll(ABCClient _Client, ABCEvent.eEventID _eID)
        {
            // Add the client to the appropriate list
            m_ClientLists[(int)_eID].Remove(_Client);
        }

        /// <summary>
        /// Sends an event to the event system for processing.
        /// </summary>
        /// <param name="_Event">The event to send.</param>
        public static void SendEvent(ABCEvent _Event)
        {
            // Enqueue the event for later processing
            m_EventList.Enqueue(_Event);
        }

        public static void Initialize()
        {
            m_ClientLists = new List<ABCClient>[(int)ABCEvent.eEventID.COUNT];
            m_EventList = new Queue<ABCEvent>();

            for (int iClientList = 0; iClientList < (int)ABCEvent.eEventID.COUNT; ++iClientList)
            {
                m_ClientLists[iClientList] = new List<ABCClient>();
            }
        }

        /// <summary>
        /// Dispatches events to all clients and then disposes of all events..
        /// </summary>
        public static void ProcessEvents()
        {
            // While the queue still has events to process
            while (m_EventList.Count > 0)
            {
                // Dequeue the next event
                ABCEvent Event = m_EventList.Dequeue();

                // For each client registered for this event
                for (int iClient = 0; iClient < m_ClientLists[(int)Event.eID].Count; ++iClient)
                {
                    // Handle the event
                    m_ClientLists[(int)Event.eID][iClient].HandleEvent(Event);
                }
            }
        }
    }
}
